From dc4db405d2991d3ec6a114f3b08d3fccd057d3ee Mon Sep 17 00:00:00 2001 From: Wolfgang Müller Date: Thu, 13 Feb 2025 17:52:16 +0100 Subject: frontend: Migrate to Svelte 5 --- frontend/src/routes/comics/[id]/+page.svelte | 177 +++++++++++++-------------- 1 file changed, 82 insertions(+), 95 deletions(-) (limited to 'frontend/src/routes/comics/[id]/+page.svelte') diff --git a/frontend/src/routes/comics/[id]/+page.svelte b/frontend/src/routes/comics/[id]/+page.svelte index cfc5840..48c588f 100644 --- a/frontend/src/routes/comics/[id]/+page.svelte +++ b/frontend/src/routes/comics/[id]/+page.svelte @@ -2,12 +2,14 @@ import { beforeNavigate } from '$app/navigation'; import { updateComics } from '$gql/Mutations'; import { comicQuery } from '$gql/Queries'; - import { comicEquals } from '$gql/Utils'; - import { UpdateMode, type FullComicFragment, type UpdateComicInput } from '$gql/graphql'; - import { initReaderContext } from '$lib/Reader'; - import { initScraperContext } from '$lib/Scraper'; - import { initSelectionContext } from '$lib/Selection'; - import { setTabContext } from '$lib/Tabs'; + import { omitIdentifiers, type OmitIdentifiers } from '$gql/Utils'; + import { + UpdateMode, + type FullComicFragment, + type PageFragment, + type UpdateComicInput + } from '$gql/graphql'; + import { comicPending } from '$lib/Form'; import { toastFinally } from '$lib/Toasts'; import { preventOnPending } from '$lib/Utils'; import BookmarkButton from '$lib/components/BookmarkButton.svelte'; @@ -21,155 +23,140 @@ import ComicForm from '$lib/forms/ComicForm.svelte'; import Gallery from '$lib/gallery/Gallery.svelte'; import PageView from '$lib/reader/PageView.svelte'; - import Reader from '$lib/reader/Reader.svelte'; + import Reader, { initReaderContext } from '$lib/reader/Reader.svelte'; import ComicScrapeForm from '$lib/scraper/ComicScrapeForm.svelte'; + import { initScraperContext } from '$lib/scraper/Scraper.svelte'; + import { initSelectionContext } from '$lib/selection/Selection.svelte'; import ComicDelete from '$lib/tabs/ComicDelete.svelte'; import ComicDetails from '$lib/tabs/ComicDetails.svelte'; import Tab from '$lib/tabs/Tab.svelte'; import Tabs from '$lib/tabs/Tabs.svelte'; import SelectionControls from '$lib/toolbar/SelectionControls.svelte'; import { getContextClient } from '@urql/svelte'; - import type { PageData } from './$types'; + import { untrack } from 'svelte'; + import type { PageProps } from './$types'; + let { data }: PageProps = $props(); const client = getContextClient(); const reader = initReaderContext(); - const selection = initSelectionContext(); const scraper = initScraperContext(); - const tabContext = setTabContext({ - tabs: { - details: { title: 'Details' }, - edit: { title: 'Edit' }, - scrape: { title: 'Scrape' }, - deletion: { title: 'Delete' } - }, - current: 'details' - }); + const selection = initSelectionContext('Page', (p) => p.path); - export let data: PageData; - $: result = comicQuery(client, { id: data.id }); - - let comic: FullComicFragment; - let original: Readonly; - let updatePartial = false; - - $: $result, update(); - $: pending = !comicEquals(comic, original); - $: $tabContext.tabs.edit.badge = pending; - - function update() { - if (!$result.stale && $result.data?.comic.__typename === 'FullComic') { - original = $result.data.comic; - if (updatePartial) { - comic.pages = structuredClone(original.pages); - comic.favourite = original.favourite; - comic.bookmarked = original.bookmarked; - comic.organized = original.organized; - comic.updatedAt = original.updatedAt; - updatePartial = false; - } else { - comic = structuredClone(original); - } - - $reader.pages = original.pages; - $selection.view = comic.pages; - $scraper.selector = undefined; - } + let comic: FullComicFragment | undefined = $state(); + let input: OmitIdentifiers | undefined = $state(); + let updateInput = $state(true); + + function invalidateInput() { + updateInput = true; } - function toggle(field: keyof Omit) { - updateComics(client, { ids: comic.id, input: { [field]: !comic[field] } }) - .then(() => (updatePartial = true)) - .catch(toastFinally); + function submit(input: UpdateComicInput) { + updateComics(client, { ids: data.id, input }).then(invalidateInput).catch(toastFinally); } - function updateComic(event: CustomEvent) { - updateComics(client, { ids: comic.id, input: event.detail }).catch(toastFinally); + function toggle(field: keyof Pick) { + if (!comic) return; + updateComics(client, { ids: data.id, input: { [field]: !comic[field] } }).catch(toastFinally); } - function updateCover(event: CustomEvent) { - updateComics(client, { ids: comic.id, input: { cover: { id: event.detail } } }) - .then(() => (updatePartial = true)) - .catch(toastFinally); + function updateCover(id: number) { + updateComics(client, { ids: data.id, input: { cover: { id } } }).catch(toastFinally); } function removePages() { updateComics(client, { - ids: comic.id, - input: { pages: { ids: $selection.ids, options: { mode: UpdateMode.Remove } } } + ids: data.id, + input: { pages: { ids: selection.ids, options: { mode: UpdateMode.Remove } } } }) - .then(() => { - updatePartial = true; - $selection = $selection.clear(); - }) + .then(selection.clear) .catch(toastFinally); } beforeNavigate((navigation) => preventOnPending(navigation, pending)); + let result = $derived(comicQuery(client, { id: data.id })); + let pending = $derived(comicPending(comic, input)); + + $effect(() => { + if (!$result.stale) { + untrack(() => { + if ($result.data?.comic.__typename === 'FullComic') { + comic = $result.data.comic; + + if (updateInput) { + input = omitIdentifiers($result.data.comic); + updateInput = false; + } + + reader.pages = comic.pages; + selection.view = comic.pages; + scraper.reset(); + } + }); + } + }); - + -{#if comic} +{#if comic && input}
toggle('favourite')} + title={comic.title} + subtitle={comic.originalTitle} + favourite={comic.favourite} + onfavourite={() => toggle('favourite')} />
- ($reader = $reader.open(e.detail))} - on:cover={updateCover} - /> +
- - -
- -
-
-
+ {#snippet sidebar()} + {#if input} + +
+ +
+
+ {/if} + {/snippet}
{:else} -- cgit v1.2.3-2-gb3c3